﻿using LuaInterface;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ScriptBase : MonoBehaviour
{
    private AssetManager mAssetManager;
    private AssetManager _AssetManager
    {
        get
        {
            if (mAssetManager == null)
                mAssetManager = AppFacade.Instance.GetManager<AssetManager>(FacadeConfig.AssetManager);
            return mAssetManager;
        }
    }

    private ViewManager mViewManager;
    public ViewManager _ViewManager
    {
        get
        {
            if (mViewManager == null)
                mViewManager = AppFacade.Instance.GetManager<ViewManager>(FacadeConfig.ViewManager);
            return mViewManager;
        }
    }

    private MsgController mMsgController;
    public MsgController _MsgController
    {
        get
        {
            if (mMsgController == null)
                mMsgController = AppFacade.Instance.GetManager<MsgController>(FacadeConfig.MsgController);
            return mMsgController;
        }
    }

    private LuaScriptMgr mLuaScriptMgr;
    public LuaScriptMgr _LuaScriptMgr
    {
        get
        {
            if (mLuaScriptMgr == null)
                mLuaScriptMgr = AppFacade.Instance.GetManager<LuaScriptMgr>(FacadeConfig.LuaScriptMgr);
            return mLuaScriptMgr;
        }
    }

    private VersionManager mVersionManager;
    public VersionManager _VersionManager
    {
        get
        {
            if (mVersionManager == null)
                mVersionManager = AppFacade.Instance.GetManager<VersionManager>(FacadeConfig.VersionManager);
            return mVersionManager;
        }
    }

    private DownloadManager mDownloadManager;
    public DownloadManager _DownloadManager
    {
        get
        {
            if (mDownloadManager == null)
                mDownloadManager = AppFacade.Instance.GetManager<DownloadManager>(FacadeConfig.DownloadManager);
            return mDownloadManager;
        }
    }

    #region 资源管理相关
    /// <summary>
    /// 用于收集界面加载的对象路径，以便统一卸载
    /// </summary>
    private List<string> mAssetPathList = new List<string>();

    public void RecordLoadPath(string tPath)
    {
        mAssetPathList.Add(tPath);
    }

    /// <summary>
    /// 加载资源
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="tPath"></param>
    /// <returns></returns>
    public virtual T GetAsset<T>(string tPath) where T : class
    {
        T mAsset = _AssetManager.GetAsset<T>(tPath);
        RecordLoadPath(tPath);
        return mAsset;
    }

    /// <summary>
    /// 加载GameObject
    /// </summary>
    /// <param name="tPath"></param>
    /// <param name="tSelfRecord">是否将加载的路径记录在加载对象自己身上</param>
    /// <returns></returns>
    public virtual GameObject GetGameObject(string tPath, bool tSelfRecord = false)
    {
        GameObject mObj = _AssetManager.GetGameObject(tPath);
        if (tSelfRecord)
            mObj.GetComponent<ScriptBase>().RecordLoadPath(tPath);
        else
            RecordLoadPath(tPath);
        return mObj;
    }
    #endregion 资源管理相关


    #region Lua相关
    public string mLuaClassName;
    private LuaTable mLuaTable;
    //收集点击事件方法
    private List<LuaFunction> mCollectFuncList = new List<LuaFunction>();
    //收集协程方法
    private List<LuaFunction> mCollectEnumFunclist = new List<LuaFunction>();
    #endregion Lua相关


    void Awake()
    {
        if (string.IsNullOrEmpty(mLuaClassName))
            return;

        object[] obj = CallLuaFunction("Awake", gameObject);
        if (obj != null)
            mLuaTable = (LuaTable)obj[0];
        //if (mLuaTable == null)
        //{
        //    Debug.LogError("找不到对应Lua文件");
        //}
    }

    void Start()
    {
        if (mLuaTable != null)
        {
            CallLuaFunction("Start", mLuaTable);
        }
    }

    public void AddClick(GameObject sender, LuaFunction tFunc)
    {
        UIEventListener.Get(sender).onClick = delegate (GameObject o)
        {
            tFunc.Call(o);
        };
        mCollectFuncList.Add(tFunc);
    }

    public void WaitForFrameToDo(LuaFunction tFunc, int tFramecount, int tLooptime)
    {
        mCollectEnumFunclist.Add(tFunc);
        StartCoroutine(WaitForFrameToDoIEnum(tFunc, tFramecount, tLooptime));
    }
    IEnumerator WaitForFrameToDoIEnum(LuaFunction tFunc, int tFramecount, int tLooptime)
    {
        if (tLooptime == -1)//慎用
        {
            while (true)
            {
                for (int i = 0; i < tFramecount; i++)
                {
                    yield return new WaitForEndOfFrame();
                }
                tFunc.Call();
            }
        }
        else if (tLooptime >= 0)
        {
            while (tLooptime >= 0)
            {
                for (int i = 0; i < tFramecount; i++)
                {
                    yield return new WaitForEndOfFrame();
                }
                tFunc.Call();
                tLooptime--;
            }
            mCollectEnumFunclist.Remove(tFunc);
            tFunc.Release();
        }
    }

    public void WaitForSecondsToDo(LuaFunction tFunc, float tDuration, int tLooptime)
    {
        mCollectEnumFunclist.Add(tFunc);
        StartCoroutine(WaitForSecondsToDoIEnum(tFunc, tDuration, tLooptime));
    }
    IEnumerator WaitForSecondsToDoIEnum(LuaFunction tFunc, float tDuration, int tLooptime)
    {
        if (tLooptime == -1)//慎用
        {
            while (true)
            {
                yield return new WaitForSeconds(tDuration);
                tFunc.Call();
            }
        }
        else if (tLooptime >= 0)
        {
            while (tLooptime >= 0)
            {
                yield return new WaitForSeconds(tDuration);
                tFunc.Call();
                tLooptime--;
            }
            mCollectEnumFunclist.Remove(tFunc);
            tFunc.Release();
        }
    }

    object[] CallLuaFunction(string tFuncName, params object[] args)
    {
        LuaScriptMgr uluaMgr = _LuaScriptMgr;
        return uluaMgr.CallLuaFunction(mLuaClassName + "." + tFuncName, args);
    }

    /// <summary>
    /// 处理消息
    /// </summary>
    /// <param name="msg"></param>
    public virtual void ReceiveMsg(object msg)
    {
        if (mLuaTable != null)
        {
            CallLuaFunction("ReceiveMsg", mLuaTable, msg);
        }
    }

    void OnEnable()
    {
        if (mLuaTable != null)
        {
            CallLuaFunction("OnEnable", mLuaTable);
        }
    }

    void OnDisable()
    {
        if (mLuaTable != null)
        {
            CallLuaFunction("OnDisable", mLuaTable);
            for (int i = 0; i < mCollectEnumFunclist.Count; i++)
            {
                mCollectEnumFunclist[i].Release();
            }
            mCollectEnumFunclist.Clear();
        }
    }

    protected virtual void OnDestroy()
    {
        if (mLuaTable != null)
        {
            CallLuaFunction("OnDestroy", mLuaTable);
            if (mLuaTable != null)
            {
                mLuaTable.Release();
            }
            for (int i = 0; i < mCollectFuncList.Count; i++)
            {
                mCollectFuncList[i].Release();
            }
            _LuaScriptMgr.CallLuaFunction("LuaGC");
        }
        for (int i = 0; i < mAssetPathList.Count; i++)
            _AssetManager.UnLoadUnUseAsset(mAssetPathList[i]);
    }
}
